#!/usr/bin/python3
# -*- coding: utf-8 -*-
import re
from api import netbox_api, zabbix_api6
import traceback
from api.universal import change_datetime
from api.universal import bandwidth_change
from loguru import logger
logger.add("/var/log/Task/Tasks.log", rotation="00:00", backtrace=True, diagnose=True, level="DEBUG")

# 计数初始化
cablescount = 0  # 外网与mpls线路
addhosts = 0  # 线路总数
updatelines = 0  # 更新总数
newlines = 0  # 新建总数
# 变量初始化
x_name = ''
line_no_ip_num = 0
netbox_list = 0
no_ip_list = []

# 日志输出常量定义
# logger = logging.getLogger('netbox')


# 通过circuit获取cable信息
def get_cable_info(data, netbox_url, netbox_token, verify):
    try:
        url = f'{netbox_url}/api/dcim/cables/?limit=100'
        while 1:
            logger.info(f"url------->{url}")
            # 拿到circuit_id
            circuit_id = data["id"]
            # 获取所有的 cable 的 id
            resp = netbox_api.netbox_get_next(netbox_token, url, verify)
            logger.info(resp)
            for i in resp["results"]:
                if i["termination_a"]["circuit"]['id'] == circuit_id:
                    return i
            url = resp["next"]
    except Exception as e:
        # logger.info(f"通过circuit获取cable信息失败：{traceback.format_exc()}")
        logger.info(traceback.format_exc())
        resp_data = {
            "status": "Error",
            "message": "通过circuit获取cable信息失败",
            "detail": traceback.format_exc(),
            "hostname": f"拿到circuit_id:{data['id']}"
        }
        logger.exception(traceback.format_exc())
        return resp_data



# 通过cable获取circuit信息
def get_circuit_info(data, netbox_token):
    try:
        # 拿到circuit_id
        if data["termination_a"].get("circuit", None):
            circuit_url = data["termination_a"]["circuit"]["url"]
        else:
            circuit_url = data["termination_b"]["circuit"]["url"]
        circuit_info = netbox_api.netbox_get_next(netbox_token, circuit_url, False)
        return circuit_info
    except Exception as e:
        # logger.error(f"获取circuit信息失败，错误信息：{traceback.format_exc()}")
        logger.info(traceback.format_exc())
        resp_data = {
            "status": "Error",
            "message": "通过cable获取circuit信息失败",
            "detail": traceback.format_exc()
        }
        logger.exception(traceback.format_exc())
        return resp_data


# --------zabbix 创建线路函数---2.1--------
def zabbix_create_line(hostip, hostname, name, groups, templateid, port_type, macros, inventory, tags, search_info,
                       line_status, last_date, forcibly_update, token, zabbix_server_url, proxy_hostid):
    # global addhosts, search_ret, updatelines, newlines, logger

    try:
        global addhosts, search_ret, updatelines, newlines
        # forcibly_update=1 # 强制更新开关 1 为强制更新
        creat_ret = None
        addhosts = addhosts + 1
        # 检索zabbix是否有这台host
        search_ret = zabbix_api6.zabbix_get_macros(token, zabbix_server_url, 'search', search_info)
        if 'result' in search_ret:
            if not len(search_ret['result']):
                search_ret = zabbix_api6.zabbix_get_hosts(token, zabbix_server_url, 'host', hostname)
                if 'result' in search_ret:
                    if not len(search_ret['result']):
                        # logger.info(f"正在创建zabbix_host:{hostname}")
                        # print("正在创建zabbix_host:" + hostname)
                        creat_ret = zabbix_api6.zabbix_create_line(token, zabbix_server_url, hostip, hostname, name, groups,
                                                                   templateid, port_type, macros, inventory, tags,
                                                                   line_status, proxy_hostid)
                        # if type(creat_ret) == dict and creat_ret.get("status") == "Error":
                        #     return creat_ret

                    else:
                        creat_ret = zabbix_update_line(search_ret['result'][0]['hostid'], hostip, hostname, name, groups,
                                                       templateid,
                                                       port_type, macros, inventory, tags, line_status, token,
                                                       zabbix_server_url)
                    # if type(creat_ret) == dict and creat_ret.get("status") == "Error":
                    return creat_ret
            else:
                # logger.info(f"线路{name}已存在，正在检测更新···")
                logger.info('线路' + name + '已存在，正在检测更新···')
                c_ret = search_ret['result'][0]['hostid']
                macros_ret = zabbix_api6.zabbix_get_macros(token, zabbix_server_url, 'hostids',
                                                           search_ret['result'][0]['hostid'])
                # 判断netbox线路更新时间是否比zabbix新
                x_date = ""
                for x in macros_ret['result']:
                    if x['macro'] == '{$UPDATA_DATE}':
                        x_date = x['value']
                zabbix_date = change_datetime(x_date)
                if last_date > zabbix_date or forcibly_update == 1:
                    zabbix_update_data = zabbix_update_line(search_ret['result'][0]['hostid'], hostip, hostname, name, groups, templateid,
                                       port_type, macros, inventory, tags, line_status, token, zabbix_server_url)
                    # if type(zabbix_update_data) == dict and zabbix_update_data.get("status") == "Error":
                    return zabbix_update_data
                else:
                    # logger.info(f"线路{hostname}未检测到更新")
                    logger.info(f"线路{hostname}未检测到更新")
        # logger.info(creat_ret)
        # if not creat_ret:
        #     # return 0
        #     resp_data = 0
        # else:
        #     # c_ret = creat_ret['result']['hostids'][0]
        #     resp_data = creat_ret['result']['hostids'][0]
        resp_data = {
            "status": "None",
            "message": f"线路{hostname}无更新",
            "hostname": hostname
        }
        return resp_data
    except Exception as e:
        resp = {
            "status": "Error",
            "message": "zabbix 创建线路失败",
            "detail": traceback.format_exc(),
            "hostname": hostname
        }
        logger.exception(traceback.format_exc())
        return resp


# --------zabbix 更新线路函数--2.2---------
def zabbix_update_line(hostid, hostip, hostname, name, groups, templateid, port_type, macros, inventory, tags,
                       line_status, token, zabbix_server_url):
    try:
        # global updatelines, logger
        global updatelines
        # logger.info(f"检测到line {hostname}信息有更新，正在更新")
        logger.info('检测到line信息有更新，正在更新')
        # 获取host接口ID
        zabbix_ret = zabbix_api6.zabbix_get_hostinterface(token, zabbix_server_url, hostid)
        # 更新监控非IP信息
        update_ret1 = zabbix_api6.zabbix_update_line(token, zabbix_server_url, hostid, hostip, hostname, name, groups,
                                                     templateid, port_type, macros, inventory, tags, line_status)
        if type(update_ret1) == dict and update_ret1.get("status") == "Error":
            return update_ret1
        # 比较IP，如有更改，则更新IP
        if hostip != zabbix_ret['result'][0]['ip']:
            update_ret2 = zabbix_api6.zabbix_uptade_hostinterface(token, zabbix_server_url, zabbix_ret['result'][0]['interfaceid'], hostip)
            if type(update_ret2) == dict and update_ret2.get("status") == "Error":
                update_ret2["hostname"] = hostname
                return update_ret2
        # logger.info(f"line {name} IP信息已更新")
        logger.info('line' + name + ' IP信息已更新')
        resp_data = {
            "status": "Update",
            "mesage": "更新线路成功",
            "hostname": hostname,
            "zabbix_ret": update_ret1
        }
        return resp_data
    except Exception as e:
        resp_data = {
            "status": "Error",
            "message": "更新失败",
            "detail": traceback.format_exc()
        }
        logger.exception(traceback.format_exc())
        return resp_data


# --------根据cables列表创建host---------
def update_cables(x, token, zabbix_server_url, netbox_token, father_template_group, netbox_url, proxy_hostid):
    try:
        # f = open('sync_error.log', 'a')
        global x_name, cablescount, addhosts, n, last_data, line_no_ip_num, no_ip_list
        # global x_name, cablescount, addhosts, n, last_data, line_no_ip_num, no_ip_list, logger
        # print("开始轮询netboxcables")
        # logger.info("开始轮询netboxcables")
        # for x in cablesList:
        # 将 name 对象解析为 name， 由接口返回结果知 name 是一个列表（数组）
        # 如果当前hostname与上个hostname相同（堆叠设备），则跳过此次循环，进入下一轮循环
        # 排除，不作处理的hosts
        # if x_name==x['name'] or re.search("(.*asw.*)|(.*dsw.*)", x['name'], re.I) :
        #	 break;
        # ------------根据cable两端连接设备类型判断是否特殊线路
        # TODO update 线路命名逻辑，线路判断逻辑，以保证每条线路监控不重复
        logger.info(x)
        cableid = x['id']
        if 'circuit' in x['termination_a'].keys() and 'device' in x['termination_b'].keys():
            cablescount = cablescount + 1
            device = x['termination_b']['device']
            circuit = x['termination_a']['circuit']
            # 设备名+接口+ip+运营商+带宽
            host_name = x['termination_b']['device']['name'] + '-' + x['termination_b']['name']
        elif 'device' in x['termination_a'].keys() and 'circuit' in x['termination_b'].keys():
            cablescount = cablescount + 1
            if x['termination_a'].get('device', None):
                device = x['termination_a']['device']
                circuit = x['termination_b']['circuit']
            else:
                device = x['termination_a']['circuit']
                circuit = x['termination_b']['device']

            # 设备名+接口+ip+运营商+带宽
            host_name = x['termination_a']['device']['name'] + '-' + x['termination_b']['name']
        else:
            # logger.info(f"this cable {x['display']} is invalid")
            resp_data = {"status": "Error",
                         "message": f"this cable {x['display']} is invalid",
                         "detail": f"this cable {x['display']} is invalid",
                         }
            return resp_data
        host_name = host_name.replace('/', '-')
        gw_host_name = host_name + '-next'

        # -------------------查询circuit信息
        url = circuit['url']
        if url.startswith("http"):
            netbox_url_new_3 = circuit['url']
        else:
            netbox_url_new_3 = netbox_url + circuit['url']

        circuit_info = netbox_api.netbox_get_next(netbox_token, netbox_url_new_3, False)
        last_updated = circuit_info['last_updated']
        # 提取更新日期
        last_date = change_datetime(last_updated)
        # 带宽单位显示转换
        bandwidth = bandwidth_change(circuit_info['commit_rate'], 'KB')

        logger.info(circuit_info)
        line_status = 0
        if circuit_info['status']['label'] == 'Active':
            line_status = 0
        elif circuit_info['status']['label'] != 'Active':
            line_status = 1
        if circuit_info['custom_fields']['IPAddress'] == None:
            line_no_ip_num = line_no_ip_num + 1
            line_info = '\n' + str(line_no_ip_num) + ' ' + host_name + '-' + str(
                circuit_info['custom_fields']['IPAddress']) + '-' + str(circuit_info['provider']['slug']) + '-' + str(
                bandwidth)
            no_ip_list.append(line_info)
            f = open('../lines_no_ip.list', 'a')
            f.write(line_info)
            f.close()
            # resp_data = {
            #     "message": f"{str(line_no_ip_num)}' '{host_name}-{str(circuit_info['custom_fields']['IPAddress'])}-{str(circuit_info['provider']['slug'])}-{str(bandwidth)}"}
            # logger.info("该线路a端没有IP，不创建线路")
            resp_data = {"status": "None",
                         "messsage": f"{str(line_no_ip_num)} {host_name}-{str(circuit_info['custom_fields']['IPAddress'])}-{str(circuit_info['provider']['slug'])}-{str(bandwidth)}",
                         "detail": "该线路没有IP，不创建线路",
                         "hostname": host_name
                         }
            return resp_data

        line_type = circuit_info['type']['name']
        host_ip_re = re.search('((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)',
                             circuit_info['custom_fields']['IPAddress'])
        if host_ip_re:
            host_ip = host_ip_re.group()
        else:
            resp_data = {
                "status": "None",
                "message": "无固定IP，跳过",
                "hostname": host_name
            }
            return resp_data


        display_name = host_name + '-' + str(host_ip) + '-' + str(circuit_info['provider']['name']) + '-' + str(
            bandwidth)
        gw_display_name = host_name + '-' + str(circuit_info['custom_fields']['Gateway']) + '-next-' + str(
            circuit_info['provider']['name']) + '-' + str(bandwidth)
        logger.info('检索到线路:' + display_name)
        # ----------------查询device信息
        if device['url'].startswith("http"):
            netbox_url_new = device['url']
        else:
            netbox_url_new = netbox_url + device['url']
        # https://netbox.int.xiaohongshu.com/api/dcim/devices/380/

        # device_info = netbox_api.netbox_get_next(netbox_token, device['url'], False)
        device_info = netbox_api.netbox_get_next(netbox_token, netbox_url_new, False)
        # logger.info("device_info--------->", device_info)
        # 获取办公区信息
        netbox_url_new_2 = netbox_url + device_info['site']['url']
        # https://netbox.int.xiaohongshu.comhttps://netbox.int.xiaohongshu.com/api/dcim/sites/1/

        site_info = netbox_api.netbox_get_next(netbox_token, device_info['site']['url'], False)
        # site_info = netbox_api.netbox_get_next(netbox_token, netbox_url_new_2, False)
        site_name = device_info['site']['slug'] + '-' + device_info['site']['name']
        priority = str(site_info['custom_fields']['Priority'])
        template = priority + ' lines'
        # 如果站点状态非active，2，则跳过此线路
        if site_info['status']['value'] not in ["active"]:
            resp_data = {
                "status": "None",
                "message": f"站点状态为：{site_info['status']['label']}跳过此线路",
                "detail": f"站点状态为：{site_info['status']['label']}跳过此线路",
                "hostname": x["name"]
            }
            return resp_data
        # department = device_info['tenant']['name']
        if device_info.get("tenant"):
            department = device_info['tenant']['name']
        else:
            department = None
        # -----------------创建站点，模板与主机-----------------------
        macros = ''
        groups = ''
        # 按线路类型分组
        # group_info1 = zabbix_api6.zabbix_get_group(token, zabbix_server_url, 'name', 'Netbox ' + line_type, '0')
        group_info1 = zabbix_api6.zabbix_get_group(token, zabbix_server_url, 'name', 'Netbox ' + line_type, False)

        if not group_info1:
            ret = zabbix_api6.zabbix_create_group(token, zabbix_server_url, 'Netbox ' + line_type)
            logger.info(ret)
            if type(ret) == dict and ret.get("status") == "Error":
                ret["hostname"] = x["name"]
                return ret
            group_id1 = ret['result']['groupids'][0]

        # 按站点分组
        else:
            group_id1 = group_info1[0]['groupid']
        # group_info2 = zabbix_api6.zabbix_get_group(token, zabbix_server_url, 'name', site_name + '*', '0')
        group_info2 = zabbix_api6.zabbix_get_group(token, zabbix_server_url, 'name', site_name + '*', False)

        # 增加宏
        if x.get("termination_z", None):
            resp = get_status_value(x, netbox_url, netbox_token)
            if resp.get("status") == "Error":
                return resp
        else:
            circuit_information = get_circuit_info(x, netbox_token)
            if type(circuit_information) == dict and circuit_information.get("status") == "Error":
                circuit_information["hostname"] = x["name"]
                return circuit_information
            resp = get_status_value(circuit_information, netbox_url, netbox_token)
            if resp.get("status") == "Error":
                return resp

        # 检查线路状态
        # if not status_check(circuit_info['status']['label']):
        if circuit_info['status']['label'] != "Active":
            search_info = {
                "macro": "{$CIRCUIT_ID}",
                "value": "netbox_" + str(circuit_info['id']) + "_end"
            }
            ret = zabbix_api6.zabbix_get_macros(token, zabbix_server_url, 'search', search_info)
            if ret:
                for i in ret['result']:
                    logger.info(i)
                    host_id = i['hostid']
                    resp_update_host = zabbix_api6.zabbix_update_host(token, zabbix_server_url, host_id, 'status', 1)
                    if type(resp_update_host) == dict and resp_update_host.get("status") == "Error":
                        return resp_update_host
            else:
                # logger.error("IP no change")
                logger.info('IP no change.\n')

        if group_info2:
            group_id2 = group_info2[0]['groupid']
            groups = [{
                "groupid": group_id1
            }, {
                "groupid": group_id2
            }
            ]
            macros = [
                {
                    "macro": "{$CABLE_ID}",
                    "value": "netbox_" + str(cableid) + "_end",
                    "description": "local"
                }, {
                    "macro": "{$CIRCUIT_ID}",
                    "value": "netbox_" + str(circuit['id']) + "_end",
                    "description": "local"
                }, {
                    "macro": "{$DEVICE_ID}",
                    "value": "zabbix_" + str(device['id']) + "_end"
                }, {
                    "macro": "{$DEVICE_IP}",
                    "value": "netbox_" + str(device_info['custom_fields']['ManagementIP']) + "_end"
                }, {
                    "macro": "{$UPDATA_DATE}",
                    "value": str(last_updated)
                },
                {
                    "macro": "{$NEXT_ID}",
                    "value": "0"
                }, {
                    "macro": "{$SITE_CODE}",
                    "value": str(site_info.get('slug'))
                }, {
                    "macro": "{$SITE_NAME}",
                    "value": str(site_info.get('name'))
                }, {
                    "macro": "{$SITE_STATUS}",
                    "value": site_info['status']['label'],
                    "description": str(site_info['status']['value'])
                }, {
                    "macro": "{$DEVICE_ROLE}",
                    "value": 'line_' + str(line_type),
                }, {
                    "macro": "{$LINE_STATUS}",
                    "value": str(resp["LINE_STATUS"]),
                    "description": str(resp["LINE_VALUE"])
                }, {
                    "macro": "{$DEVICE_STATUS}",
                    "value": str(resp["DEVICE_STATUS"]),
                    "description": str(resp["DEVICE_VALUE"])
                }, {
                    "macro": "{$DFA_NAME}",
                    "value": str(resp["DFA_NAME"]),
                    "description": str(resp["DFA_VALUE"])
                }, {
                    "macro": "{$DFZ_NAME}",
                    "value": str(resp["DFZ_NAME"]),
                    "description": str(resp["DFZ_VALUE"])
                }, {
                    "macro": "{$NETBOX_MODULE}",
                    "value": "device",
                }
            ]
            inventory = {
                "poc_1_name": department,
                "location": site_info.get('name'),
                "site_address_a": site_info.get('physical_address'),
                "location_lat": site_info.get('latitude'),
                "location_lon": site_info.get('longitude')
            }
            tags = [
                {
                    "tag": "department",
                    "value": "Netops"
                },
                {
                    "tag": "device_type",
                    "value": str(template)
                }, {
                    "tag": "device_role",
                    "value": 'line_' + str(line_type)
                }, {
                    "tag": "line_status",
                    "value": str(resp["LINE_STATUS"]),
                }, {
                    "tag": "device_status",
                    "value": str(resp["DEVICE_STATUS"]),
                }, {
                    "tag": "site_status",
                    "value": str(site_info['status']['label']),
                }, {
                    "tag": "netbox_module",
                    "value": "device",
                }
            ]
            logger.info('检索template_id')
            # logger.info(f'检索{template} template_id')
            template_info = zabbix_api6.zabbix_get_templates(token, zabbix_server_url, 'name', template)
            if template_info:
                template_id = template_info[0]['templateid']
            else:
                template_id = None
            # 创建gw next信息
            while 1:
                if template_id:
                    logger.info(template_info)
                    # 调用主机创建函数,如果gw为空，则跳过gw,否则创建gw,并将ID记录到cable
                    logger.info('检查线路是否存在gw信息')
                    if circuit_info['custom_fields']['Gateway'] is not None:
                        logger.info('检索到gw信息，创建线路gw监控项' + gw_display_name + '···')
                        search_info = {
                            "macro": "{$CABLE_ID}",
                            "value": "netbox_" + str(cableid) + "_end",
                            "description": "next"
                        }
                        macros[0]['description'] = "next"
                        macros[1]['description'] = "next"
                        gw_ip = (re.search('((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)',
                                           circuit_info['custom_fields']['Gateway']).group())
                        # 修改宏与tag device_role属性 for next
                        for i in range(len(macros)):
                            if macros[i]['macro'] == "{$DEVICE_ROLE}":
                                macros[i]['value'] = 'next_' + str(line_type)
                        tags[2]['value'] = 'next_' + str(line_type)
                        next_data = zabbix_create_line(gw_ip, gw_host_name, gw_display_name, groups, template_id, '1',
                                                     macros, inventory, tags, search_info, line_status, last_date, 0,
                                                     token,
                                                     zabbix_server_url, proxy_hostid)
                        if next_data.get("zabbix_ret"):
                            next_id = next_data["zabbix_ret"]['result']['hostids'][0]
                        else:
                            next_id = 0
                        # if type(next_id) == dict and next_id.get("status") == "Error":
                        #     return next_id
                        # 修改宏与tag device_role属性 for line
                        macros[0]['description'] = "local"
                        macros[1]['description'] = "local"
                        macros[5]['value'] = str(next_id)
                        for i in range(len(macros)):
                            if macros[i]['macro'] == "{$DEVICE_ROLE}":
                                macros[i]['value'] = 'line_' + str(line_type)
                        tags[2]['value'] = 'line_' + str(line_type)
                    else:
                        logger.info('线路无gw信息')
                    logger.info('创建线路监控项' + display_name + '···')
                    search_info = {
                        "macro": "{$CABLE_ID}",
                        "value": "netbox_" + str(cableid) + "_end",
                        "description": "local"
                    }
                    host_cable = zabbix_create_line(host_ip, host_name, display_name, groups, template_id, '1', macros,
                                                    inventory, tags, search_info, line_status, last_date, 0, token,
                                                    zabbix_server_url, proxy_hostid)
                    # if type(host_cable) == dict and host_cable.get("status") == "Error":
                    #     return host_cable
                    # resp_data = {
                    #     "status": "Create",
                    #     "message": f"更新结束，创建线路监控项{display_name}",
                    #     "hostname": host_name,
                    # }
                    return host_cable

                else:
                    logger.info('未找到模板,创建中:' + template)
                    # tmp_group_info = zabbix_api6.zabbix_get_group(token, zabbix_server_url, 'name', father_template_group, '0')
                    tmp_group_info = zabbix_api6.zabbix_get_group(token, zabbix_server_url, 'name', father_template_group, False)
                    if type(tmp_group_info) == dict and tmp_group_info["status"] == "Error":
                        tmp_group_info["hostname"] = host_name
                        return tmp_group_info
                    if len(tmp_group_info):
                        tmp_group_id = tmp_group_info[0]['groupid']
                        template_info = zabbix_api6.zabbix_create_template(token, zabbix_server_url, tmp_group_id,
                                                                           template)
                        # print(str(template_info))
                        template_id = template_info['templateids'][0]
                    else:
                        logger.info(f"更新失败， 请创建templates group:{father_template_group}")
                        resp_data = {
                            "status": "Error",
                            "message": f"更新失败",
                            "detail": f"请创建templates group:{father_template_group}",
                            "hostname": host_name,
                        }
                        return resp_data

        else:
            # logger.error(f"未找到site分组{site_name}，请同步site")
            logger.info(f"未找到site分组{site_name}，请同步site")
            resp_data = {
                "status": "Error",
                "message": "更新失败",
                "detail": f"未找到site分组{site_name}，请同步site",
                "hostname": host_name,
            }
            return resp_data

        # # 检查线路状态
        # # if not status_check(circuit_info['status']['label']):
        # if circuit_info['status']['label'] != "Active":
        #     search_info = {
        #         "macro": "{$CIRCUIT_ID}",
        #         "value": "netbox_" + str(circuit_info['id']) + "_end"
        #     }
        #     ret = zabbix_api6.zabbix_get_macros(token, zabbix_server_url, 'search', search_info)
        #     if ret:
        #         for i in ret['result']:
        #             print(i)
        #             host_id = i['hostid']
        #             zabbix_api6.zabbix_update_host(token, zabbix_server_url, host_id, 'status', 1)
        #
        #     else:
        #         # logger.error("IP no change")
        #         print('IP no change.\n')
        # resp_data = {"message": "line更新结束"}
    except Exception as e:
        # logger.error(f"更新失败，错误信息为：{traceback.format_exc()}")
        resp_data = {
            "status": "Error",
            "message": "线路更新失败",
            "detail": traceback.format_exc()
        }
        logger.exception(traceback.format_exc())
        return resp_data


def get_status_value(x, netbox_url, netbox_token):
    try:
        device_status = None
        device_value = None
        device_status_a = None
        device_value_a = None
        device_status_z = None
        device_value_z = None

        # {$LINE_STATUS}
        line_status = None  # circuit状态
        line_value = None  # circuit value
        # {$DFA_NAME}
        dfa_name = None
        dfa_value = None
        dfz_name = None
        dfz_value = None

        line_status = x["status"]["label"]
        line_value = x["status"]["value"]
        if x.get("termation_a") and x["termination_a"].get("site", None):
            # circuit的a端为站点
            cable_info = get_cable_info(x, netbox_url, netbox_token, False)
            if cable_info["termination_b"].get("device", None):
                # cable b端为设备，取b端的设备状态
                device_url = cable_info["termination_b"]["device"]["url"]
                device_information = netbox_api.netbox_get_next(netbox_token, device_url, False)
                device_status_a = device_information["status"]["label"]
                device_value_a = device_information["status"]["value"]
                if device_information.get("location"):
                    dfa_name = device_information["location"]["name"]
                    dfa_value = device_information["location"]["slug"]

            elif cable_info["termination_a"].get("device", None):
                # cable a端为设备，取a端的设备信息
                device_url = cable_info["termination_a"]["device"]["url"]
                device_information = netbox_api.netbox_get_next(netbox_token, device_url, False)
                device_status_a = device_information["status"]["label"]
                device_value_a = device_information["status"]["value"]
                if device_information.get("location"):
                    dfa_name = device_information["location"]["name"]
                    dfa_value = device_information["location"]["slug"]
        elif x.get("termation_z") and x["termination_z"].get("site", None):
            # circuit的z端为站点
            cable_info = get_cable_info(x, netbox_url, netbox_token, False)
            if cable_info["termination_b"].get("device", None):
                # cable b端为设备，取b端的设备状态
                device_url = cable_info["termination_b"]["device"]["url"]
                device_information = netbox_api.netbox_get_next(netbox_token, device_url, False)
                device_status_z = device_information["status"]["label"]
                device_value_z = device_information["status"]["value"]
                if device_information.get("location"):
                    dfz_name = device_information["location"]["name"]
                    dfz_value = device_information["location"]["slug"]
            else:
                # cable a端为设备，取b端的设备状态
                device_url = cable_info["termination_a"]["device"]["url"]
                device_information = netbox_api.netbox_get_next(netbox_token, device_url, False)
                device_status_z = device_information["status"]["label"]
                device_value_z = device_information["status"]["value"]
        if x.get("termination_a") and x.get("termination_a").get("provider_network", None):
            # circuit a端为运营商网络， 取a端运营商网络信息
            provider_url = x["termination_a"]["provider_network"]["url"]
            privider_info = netbox_api.netbox_get_next(netbox_token, provider_url, False)
            dfa_name = privider_info["name"]
            dfa_value = privider_info["provider"]["name"]
        elif x.get("termination_z") and x.get("termination_z").get("provider_network", None):
            # circuit 如果z端为运营商网络， 则取z端的运营商信息
            provider_url = x["termination_z"]["provider_network"]["url"]
            privider_info = netbox_api.netbox_get_next(netbox_token, provider_url, False)
            dfz_name = privider_info["name"]
            dfz_value = privider_info["provider"]["name"]

        if device_status_a == "Active" and device_status_z:
            device_status = device_status_z
            device_value = device_value_z
        else:
            device_status = device_status_a
            device_value = device_value_a

        resp = {
            "DEVICE_STATUS": device_status, "DEVICE_VALUE": device_value,
            "LINE_STATUS": line_status, "LINE_VALUE": line_value,
            "DFA_NAME": dfa_name, "DFA_VALUE": dfa_value,
            "DFZ_NAME": dfz_name, "DFZ_VALUE": dfz_value
        }

        return resp
    except Exception as e:
        resp = {
            "status": "Error",
            "message": "获取宏数据出错",
            "detail": traceback.format_exc(),
            "hostname": x_name
        }
        logger.exception(traceback.format_exc())
        return resp
